﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.ObjectModel;

namespace EmbeddedLanguage.SubProcessors
{
    public class IntLoopSearchJSProcessor : ExpressionToJSProcessor
    {

        private bool Entered;

        private string CounterVar;


        protected override Expression VisitMethodOrDelegateCall(Expression node, Expression node_Object,
            MemberInfo node_Method, ReadOnlyCollection<Expression> node_Arguments, bool FromInvocation)
        {
            if (Entered)
            {
                return base.VisitMethodOrDelegateCall(node, node_Object, node_Method, node_Arguments, FromInvocation);
            }
            Entered = true;
            
            if (node_Object == null)
            {
                var ns = new NestedString
                {
                    Parent = this.CurrentNestedString,
                    Header_Template = "for(var {i} = {LB}, {lim} = {UB};  {i} < {lim}; {i}++){",
                    LHS_Template = "if({fnSearchCondition}){return {fnIfFound};}",
                    RHS = "}",
                    //ForceLineBreakOnRHS = true,
                    TreatRHSLikeBeginningOfFooter = true,
                    Footer_Template = @"return {fnIfNotFound};",
                    Comment = "IntLoopSearchJSProcessor",
                    ChildSubstitutions = new Dictionary<string, int>
                    {
                        {"{LB}", 0},
                        {"{UB}", 1},
                        {"{fnSearchCondition}", 2},
                        {"{fnIfFound}", 3},
                        {"{fnIfNotFound}", 4},
                    },
                };
                this.RemoveReturnFromParent(ns.Parent);
                this.CounterVar = ObjectEx.RootNS + "_" + this.Counter++;
                ns.Header_Template = ns.Header_Template.Replace("{i}", this.CounterVar);
                ns.Header_Template = ns.Header_Template.Replace("{lim}", this.CreateNewVariableName());
                Func<int, ExpressionToJSProcessor> processors = i =>
                {
                    switch (i)
                    {
                        case 2:
                        case 3:
                        case 4:
                            var extractor = new JSFunctionExtractor(this.CounterVar);
                            return extractor;
                    };
                    return null;
                };
                this.AddArgsToNestedString(ns, node_Arguments, processors);
            }
            else
            {
                throw new NotImplementedException();
                //this.CurrentNestedString = ns;
                //this.Visit(node_Object);
                //var nsMethodCall = new NestedString
                //{
                //    Parent = ns,
                //    LHS = "." + node_Method.Name + "(",
                //    RHS = ")",
                //};
                //this.AddArgsToNestedString(nsMethodCall, node_Arguments);
            }
            //this.CurrentNestedString = ns.Parent;
            return node;


        }
    }
}
